/* Copyright 2009 Sony Mathew, Minneapolis MN. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */
package com.xsm.gwt.widgets.client;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

/**
 * A Fluent API for laying out bunch of FlowPanels in either inline or block layout adding widgets as needed.
 * To start out, the panel is a block.
 * 
 * @author Sony Mathew
 */
public class CSSFlowPanel extends FlowPanel {

    private FlowPanel target = this;
    
    /**
     * By default this FlowPanel is block.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel() {
        getElement().getStyle().setProperty("display", "block");
    }
    
    /**
     * Create a nested FlowPanel as a block added to the current target panel.
     * Now all put(Widget) adds to this panel.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel block() {
        addTarget("block");
        return this;                
    }

    /**
     * Create a nested FlowPanel as inline added to the current target panel.
     * Now all put(Widget) adds to this panel.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel inline() {
        addTarget("inline");
        return this;
    }
        
    /**
     * Add a new target with the following display style.
     * 
     * author Sony Mathew
     */
    private void addTarget(String displayStyle) {
        FlowPanel newTarget = new FlowPanel();
        newTarget.getElement().getStyle().setProperty("display", displayStyle);
        target.add(newTarget);
        target = newTarget;        
    }
    
    /**
     * Put a widget in the current panel, 
     *  it flow inline or block and styling according to what you have on current panel.
     * author Sony Mathew
     */
    public CSSFlowPanel put(Widget w) {
        if (w != null) {
            String displayStyle = target.getElement().getStyle().getProperty("display");
            if (displayStyle != null && (displayStyle=displayStyle.trim()).length()>0) { 
                w.getElement().getStyle().setProperty("display", displayStyle);
            }
            target.add(w);
        }
        return this;
    }

    /**
     * Convenience to add text label.
     * 
     * @see put(Widget)
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel put(String text) {
        put(new Label(text));
        return this;
    }

    /**
     * Quit or close the current FlowPanel being built.
     * The target switches to the parent FlowPanel.
     * Note: cannot close the root FlowPanel.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel q() {
        if (target == this) {
            throw new IllegalStateException("Cannot close root CSSFlowPanel");
        }
        target = (FlowPanel)target.getParent();
        return this;
    }
        
    /**
     * Apply the given cssClassName to current target.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel css(String cssClassName) {
        target.addStyleName(cssClassName);
        return this;
    }
    
    
    /**
     * Set an individual style attribute on the current target SimplePanel.
     *  use inner() or outer() to change targets.
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel style(String styleAttrib, String styleValue) {
        DOM.setStyleAttribute(target.getElement(), styleAttrib, styleValue);
        return this;
    }

    /**
     * Convenience for creating a solid border using styles with the given width and color.
     */
    public CSSFlowPanel styleBorder(int width, String color) {
        style("borderStyle", "solid");
        style("borderColor", color);
        style("borderWidth", ""+width);
        return this;
    }

    /**
     * Convenience for creating a solid border using styles with default color and the given width. 
     */
    public CSSFlowPanel styleBorder(int width) {
        style("borderStyle", "solid");
        style("borderColor", "#BADBEB");
        style("borderWidth", "1");
        return this;
    }
    
    /**
     * Set the target to visible or not.
     * To set visible on the entire CSSFlowPanel, use setVisible(boolean).
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel visible(boolean visible) {
        target.setVisible(visible);
        return this;
    }
    
    /**
     * Set the Css width of the target.
     */
    public CSSFlowPanel width(String cssWidth) {
        target.setWidth(cssWidth);
        return this;
    }
    
    /**
     * Set the Css height.
     */
    public CSSFlowPanel height(String cssHeight) {
        target.setHeight(cssHeight);
        return this;
    }
    
    /**
     * Shortcut for width("100%") + height("100%")
     * 
     * author Sony Mathew
     */
    public CSSFlowPanel stretch() {
        width("100%");
        height("100%");
        return this;
    }
    
}
